package com.twotwoshop.service.search.config;

import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池
 */
@Configuration
public class ThreadPoolConfig implements AsyncConfigurer {

    /**
     * 核心线程数大小 涉及到的IO操作多 所以核心线程数为2n+1  本机核数*2 + 1
     */
    private static final int CORE_POOL_SIZE = 29;

    /**
     * 最大线程数
     */
    private static final int MAX_POOL_SIZE = 50;

    /**
     * 阻塞队列长度
     */
    private static final int QUEUE_CAPACITY = 1000;

    /**
     * 线程池维护线程所允许的空闲时间
     */
    private static final int KEEP_ALIVE_TIME = 500;


    @Bean("twotwoExecutor")
    public ExecutorService executorService() {

        //用于生成线程名称。AtomicInteger是线程安全的整数类，这里初始化为1，用于为每个线程生成唯一的名称。
        AtomicInteger c = new AtomicInteger(1);

        //阻塞队列
        LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(QUEUE_CAPACITY);

        return new ThreadPoolExecutor(
                //1.核心线程数
                CORE_POOL_SIZE,
                //2.最大线程数
                MAX_POOL_SIZE,
                //3.救济线程存活时间
                KEEP_ALIVE_TIME,
                //4.救济线程存活时间单位
                TimeUnit.MILLISECONDS,
                //5.阻塞队列
                queue,
//              //6.线程工厂
                r -> new Thread(r, "twotwo-shop-pool" + c.getAndIncrement()),
                //7.拒绝策略  这个策略会使得提交任务的线程自己来执行这个任务
                new ThreadPoolExecutor.CallerRunsPolicy()

        );

    }

    /**
     * 这段代码是Spring框架中配置线程池的典型例子，它使用@Bean注解定义了一个名为"taskExecutor"的Bean，这个Bean是一个ExecutorService类型的线程池。以下是代码的详细解释：
     * @Bean("taskExecutor")：这是一个Spring的注解，用于告诉Spring容器，下面的方法将返回一个Bean，并将其注册到Spring容器中，可以通过名称"taskExecutor"来引用这个Bean。
     * public ExecutorService executorService() { ... }：这是一个方法，返回一个ExecutorService对象，即线程池。
     * AtomicInteger c = new AtomicInteger(1);：创建一个AtomicInteger对象，用于生成线程名称。AtomicInteger是线程安全的整数类，这里初始化为1，用于为每个线程生成唯一的名称。
     * LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(QUEUE_CAPACITY);：创建一个LinkedBlockingQueue对象作为线程池的任务队列。QUEUE_CAPACITY是一个常量，表示队列的最大容量。
     * 接下来是ThreadPoolExecutor的构造函数，它有多个参数，用于配置线程池：
     * CORE_POOL_SIZE：核心线程数。即使这些线程空闲，线程池也会保持这些线程的存活，除非设置了allowCoreThreadTimeOut。
     * MAX_POOL_SIZE：最大线程数。当任务队列满了之后，线程池会创建新线程，直到线程总数达到这个值。
     * KEEP_ALIVE_TIME：非核心线程的最大空闲时间。当线程池中的线程数量超过核心线程数时，这个参数定义了超出核心线程数的那些线程在终止前可以保持空闲的时间。
     * TimeUnit.MILLISECONDS：上一个参数的时间单位，这里是毫秒。
     * queue：任务队列，用于存放等待执行的任务。
     * r -> new Thread(r, "coolshop-pool" + c.getAndIncrement())：这是一个线程工厂，用于创建新的线程。这里使用Lambda表达式创建了一个线程工厂，生成的线程名称以"coolshop-pool"开头，后跟一个递增的数字。
     * new ThreadPoolExecutor.CallerRunsPolicy()：这是一个拒绝策略。当线程池和任务队列都满了，这个策略会使得提交任务的线程自己来执行这个任务，而不是抛出异常。
     * 综上所述，这段代码配置了一个线程池，它有核心线程数、最大线程数、非核心线程的存活时间、任务队列和拒绝策略。这个线程池可以被Spring管理的其他组件注入并使用，用于执行异步任务。
     */

}














